//! 表达式

use super::{identifier::Identifier, node::Node};
use crate::{
    lexer::token::Token,
    parser::{block_statement::BlockStatement, node::NodeRoot},
};
use std::{fmt::Debug, mem::transmute, ops::Deref};

pub trait Expression: Debug {
    fn cast_to_node(&self) -> &dyn Node;
}

pub fn cast_to_node(exp: &dyn Expression) -> &NodeRoot {
    unsafe {
        let ptr = transmute::<&dyn Expression, (*const (), *const ())>(exp);
        let ptr2 = transmute::<*const (), *const NodeRoot>(ptr.0);
        &*ptr2
    }
}

pub fn cast_to_node_mut(exp: &mut dyn Expression) -> &mut NodeRoot {
    unsafe {
        let ptr = transmute::<&dyn Expression, (*const (), *const ())>(exp);
        let ptr2 = transmute::<*mut (), *mut NodeRoot>(ptr.0 as *mut ());
        &mut *ptr2
    }
}

pub fn expression_obj_to_type<T: Expression>(o: &dyn Expression) -> &T {
    unsafe {
        let ptr = transmute::<&dyn Expression, (*const T, *const ())>(o);
        &*ptr.0
    }
}

impl Clone for Box<dyn Expression> {
    fn clone(&self) -> Self {
        match self.cast_to_node().get_type() {
            "Integer" => {
                let integer = expression_obj_to_type::<Integer>(self.as_ref());
                Box::new(integer.clone())
            }
            "PrefixExpression" => {
                let pre = expression_obj_to_type::<PrefixExpression>(self.as_ref());
                Box::new(pre.clone())
            }
            "InfixExpression" => {
                let infix = expression_obj_to_type::<InfixExpression>(self.as_ref());
                Box::new(infix.clone())
            }
            "Boolean" => {
                let boolean = expression_obj_to_type::<Boolean>(self.as_ref());
                Box::new(boolean.clone())
            }
            "IfExpression" => {
                let if_express = expression_obj_to_type::<IfExpression>(self.as_ref());
                Box::new(if_express.clone())
            }
            "FunctionLiteral" => {
                let func = expression_obj_to_type::<FunctionLiteral>(self.as_ref());
                Box::new(func.clone())
            }
            "CallExpression" => {
                let call = expression_obj_to_type::<CallExpression>(self.as_ref());
                Box::new(call.clone())
            }
            "Identifier" => {
                let identifier = expression_obj_to_type::<Identifier>(self.as_ref());
                Box::new(identifier.clone())
            }
            "EqualSign" => {
                let equal_sign = expression_obj_to_type::<EqualSign>(self.as_ref());
                Box::new(equal_sign.clone())
            }
            "StringLiteral" => {
                let str = expression_obj_to_type::<StringLiteral>(self.as_ref());
                Box::new(str.clone())
            }
            "ArrayLiteral" => {
                let array = expression_obj_to_type::<ArrayLiteral>(self.as_ref());
                Box::new(array.clone())
            }
            "IndexExpression" => {
                let index = expression_obj_to_type::<IndexExpression>(self.as_ref());
                Box::new(index.clone())
            }
            "Null" => {
                let null = expression_obj_to_type::<Null>(self.as_ref());
                Box::new(null.clone())
            }
            "HashLiteral" => {
                let hash = expression_obj_to_type::<HashLiteral>(self.as_ref());
                Box::new(hash.clone())
            }
            a => panic!("不支持的Express: {}", a),
        }
    }
}
//----- 整数表达式Start--------------------------------------
#[derive(Debug, Clone)]
pub struct Integer {
    node: NodeRoot,
    token: Token,
    value: f64,
}

impl Integer {
    pub fn new(t: Token, value: f64) -> Self {
        let literal = format!("Integer value is: {}", t.literal_ref());
        let node = NodeRoot::new(literal, "Integer".to_string());
        Self {
            node,
            token: t,
            value,
        }
    }

    pub fn value(&self) -> f64 {
        self.value
    }
}

impl Expression for Integer {
    fn cast_to_node(&self) -> &dyn Node {
        &self.node
    }
}

impl Deref for Integer {
    type Target = NodeRoot;

    fn deref(&self) -> &Self::Target {
        &self.node
    }
}

//----- 前序表达式Start--------------------------------------
#[derive(Debug, Clone)]
pub struct PrefixExpression {
    node: NodeRoot,
    token: Token,
    operator: String,
    right: Box<dyn Expression>,
}

impl PrefixExpression {
    pub fn new(token: Token, operator: String, right: Box<dyn Expression>) -> Self {
        let literal = format!("({}{})", operator, right.cast_to_node().get_literal());
        let node = NodeRoot::new(literal, "PrefixExpression".to_string());
        Self {
            node,
            token,
            operator,
            right,
        }
    }

    pub fn right(&self) -> &dyn Expression {
        self.right.as_ref()
    }

    pub fn operator(&self) -> &str {
        &self.operator
    }
}

impl Expression for PrefixExpression {
    fn cast_to_node(&self) -> &dyn Node {
        &self.node
    }
}

impl Deref for PrefixExpression {
    type Target = NodeRoot;

    fn deref(&self) -> &Self::Target {
        &self.node
    }
}

//-----中序表达式--------------------------------------
#[derive(Debug, Clone)]
pub struct InfixExpression {
    node: NodeRoot,
    token: Token,
    left: Box<dyn Expression>,
    operator: String,
    right: Box<dyn Expression>,
}

impl InfixExpression {
    pub fn new(
        token: Token,
        left: Box<dyn Expression>,
        operator: String,
        right: Box<dyn Expression>,
    ) -> Self {
        let token_literal = format!(
            "({} {} {})",
            left.cast_to_node().get_literal(),
            operator,
            right.cast_to_node().get_literal()
        );

        let node = NodeRoot::new(token_literal, "InfixExpression".to_string());

        Self {
            node,
            token,
            left,
            operator,
            right,
        }
    }

    pub fn left(&self) -> &dyn Expression {
        self.left.as_ref()
    }

    pub fn right(&self) -> &dyn Expression {
        self.right.as_ref()
    }

    pub fn operator(&self) -> &str {
        &self.operator
    }
}

impl Expression for InfixExpression {
    fn cast_to_node(&self) -> &dyn Node {
        &self.node
    }
}

impl Deref for InfixExpression {
    type Target = NodeRoot;

    fn deref(&self) -> &Self::Target {
        &self.node
    }
}

//-----布尔表达式--------------------------------------
#[derive(Debug, Clone)]
pub struct Boolean {
    node: NodeRoot,
    token: Token,
    value: bool,
}

impl Boolean {
    pub fn new(token: Token, value: bool) -> Self {
        let token_literal = format!("Boolean token with value of {}", value);
        let node = NodeRoot::new(token_literal, "Boolean".to_string());
        Self { node, token, value }
    }

    pub fn value(&self) -> bool {
        self.value
    }
}

impl Expression for Boolean {
    fn cast_to_node(&self) -> &dyn Node {
        &self.node
    }
}

impl Deref for Boolean {
    type Target = NodeRoot;

    fn deref(&self) -> &Self::Target {
        &self.node
    }
}

//-----if表达式--------------------------------------
#[derive(Debug, Clone)]
pub struct IfExpression {
    node: NodeRoot,
    token: Token,
    condition: Box<dyn Expression>,
    consequence: BlockStatement,
    alternative: Option<BlockStatement>,
}

impl IfExpression {
    pub fn new(
        token: Token,
        condition: Box<dyn Expression>,
        consequence: BlockStatement,
        alternative: Option<BlockStatement>,
    ) -> Self {
        let node = NodeRoot::new(
            if let Some(alt) = &alternative {
                format!(
                    "if expression:\n\
        {}\n\
        statements in if block are:{}\n\
        statements in else are:{}",
                    condition.cast_to_node().get_literal(),
                    consequence.cast_to_node().get_literal(),
                    alt.cast_to_node().get_literal()
                )
            } else {
                format!(
                    "if expression:\n\
        {}\n\
        statements in if block are:{}",
                    condition.cast_to_node().get_literal(),
                    consequence.cast_to_node().get_literal(),
                )
            },
            "IfExpression".to_string(),
        );
        Self {
            node,
            token,
            condition,
            consequence,
            alternative,
        }
    }

    pub fn condition(&self) -> &dyn Expression {
        self.condition.as_ref()
    }

    pub fn consequence(&self) -> &BlockStatement {
        &self.consequence
    }

    pub fn alternative(&self) -> Option<&BlockStatement> {
        self.alternative.as_ref()
    }
}

impl Expression for IfExpression {
    fn cast_to_node(&self) -> &dyn Node {
        &self.node
    }
}

impl Deref for IfExpression {
    type Target = NodeRoot;

    fn deref(&self) -> &Self::Target {
        &self.node
    }
}

//-----函数表达式--------------------------------------
#[derive(Debug, Clone)]
pub struct FunctionLiteral {
    node: NodeRoot,
    token: Token,
    parameters: Vec<Identifier>,
    body: BlockStatement,
}

impl FunctionLiteral {
    pub fn new(token: Token, parameters: Vec<Identifier>, body: BlockStatement) -> Self {
        let node = NodeRoot::new(
            {
                let mut p = String::new();
                for para in &parameters {
                    p.push_str(&para.cast_to_node().get_literal());
                    p.push_str(",")
                }
                format!(
                    "token:{} parameters:{} body:{}",
                    token.literal_ref(),
                    p,
                    body.cast_to_node().get_literal()
                )
            },
            "FunctionLiteral".to_string(),
        );
        Self {
            node,
            token,
            parameters,
            body,
        }
    }

    pub fn token(&self) -> &Token {
        &self.token
    }

    pub fn parameters(&self) -> &Vec<Identifier> {
        &self.parameters
    }

    pub fn body(&self) -> &BlockStatement {
        &self.body
    }
}

impl Expression for FunctionLiteral {
    fn cast_to_node(&self) -> &dyn Node {
        &self.node
    }
}

impl Deref for FunctionLiteral {
    type Target = NodeRoot;

    fn deref(&self) -> &Self::Target {
        &self.node
    }
}

//-----函数调用表达式--------------------------------------
#[derive(Debug, Clone)]
pub struct CallExpression {
    node: NodeRoot,
    token: Token,
    function: Box<dyn Expression>, // FunctionLiteral
    arguments: Vec<Box<dyn Expression>>,
}

impl CallExpression {
    pub fn new(
        token: Token,
        function: Box<dyn Expression>,
        arguments: Vec<Box<dyn Expression>>,
    ) -> Self {
        let node = NodeRoot::new(
            {
                let mut arg = String::new();
                for a in &arguments {
                    arg.push_str(&a.cast_to_node().get_literal());
                    arg.push_str(" ");
                }
                format!(
                    "token: {} function: {} arguments: {}",
                    token.literal_ref(),
                    function.cast_to_node().get_literal(),
                    arg
                )
            },
            "CallExpression".to_string(),
        );
        Self {
            node,
            token,
            function,
            arguments,
        }
    }

    pub fn function(&self) -> &dyn Expression {
        self.function.as_ref()
    }

    pub fn token(&self) -> &Token {
        &self.token
    }

    pub fn arguments(&self) -> &Vec<Box<dyn Expression>> {
        &self.arguments
    }
}

impl Expression for CallExpression {
    fn cast_to_node(&self) -> &dyn Node {
        &self.node
    }
}

impl Deref for CallExpression {
    type Target = NodeRoot;

    fn deref(&self) -> &Self::Target {
        &self.node
    }
}

//-----赋值表达式--------------------------------------
#[derive(Debug, Clone)]
pub struct EqualSign {
    node: NodeRoot,
    left: Identifier,
    right: Box<dyn Expression>,
}

impl Deref for EqualSign {
    type Target = NodeRoot;

    fn deref(&self) -> &Self::Target {
        &self.node
    }
}

impl EqualSign {
    pub fn new(left: Identifier, right: Box<dyn Expression>) -> Self {
        let node = NodeRoot::new(left.get_literal().to_string(), "EqualSign".to_string());
        Self { node, left, right }
    }

    pub fn left(&self) -> &Identifier {
        &self.left
    }

    pub fn right(&self) -> &dyn Expression {
        self.right.as_ref()
    }
}

impl Expression for EqualSign {
    fn cast_to_node(&self) -> &dyn Node {
        &self.node
    }
}

//-----字符串表达式--------------------------------------
#[derive(Debug, Clone)]
pub struct StringLiteral {
    node: NodeRoot,
    token: Token,
}

impl Deref for StringLiteral {
    type Target = NodeRoot;

    fn deref(&self) -> &Self::Target {
        &self.node
    }
}

impl StringLiteral {
    pub fn new(tok: Token) -> Self {
        let node = NodeRoot::new(tok.literal_ref().to_string(), "StringLiteral".to_string());
        Self { node, token: tok }
    }

    pub fn token(&self) -> &Token {
        &self.token
    }
}

impl Expression for StringLiteral {
    fn cast_to_node(&self) -> &dyn Node {
        &self.node
    }
}

//-----数组表达式--------------------------------------
#[derive(Debug, Clone)]
pub struct ArrayLiteral {
    node: NodeRoot,
    token: Token,
    elements: Vec<Box<dyn Expression>>,
}

impl ArrayLiteral {
    pub fn new(token: Token, elements: Vec<Box<dyn Expression>>) -> Self {
        let mut literal = String::default();
        for e in &elements {
            literal.push_str(e.cast_to_node().get_literal());
            literal.push(',');
        }
        if elements.len() > 0 {
            let _ = literal.pop();
        }
        let node = NodeRoot::new(literal, "ArrayLiteral".to_string());
        Self {
            node,
            token,
            elements,
        }
    }

    pub fn token(&self) -> &Token {
        &self.token
    }

    pub fn elements(&self) -> &Vec<Box<dyn Expression>> {
        &self.elements
    }
}

impl Deref for ArrayLiteral {
    type Target = NodeRoot;

    fn deref(&self) -> &Self::Target {
        &self.node
    }
}

impl Expression for ArrayLiteral {
    fn cast_to_node(&self) -> &dyn Node {
        &self.node
    }
}

//-----数组访问表达式--------------------------------------
#[derive(Debug, Clone)]
pub struct IndexExpression {
    node: NodeRoot,
    token: Token,
    left: Box<dyn Expression>,
    index: Box<dyn Expression>,
}

impl IndexExpression {
    pub fn new(token: Token, left: Box<dyn Expression>, index: Box<dyn Expression>) -> Self {
        let literal = format!(
            "{}[{}]",
            left.cast_to_node().get_literal(),
            index.cast_to_node().get_literal()
        );
        let node = NodeRoot::new(literal, "IndexExpression".to_string());
        Self {
            node,
            token,
            left,
            index,
        }
    }

    pub fn token(&self) -> &Token {
        &self.token
    }

    pub fn left(&self) -> &dyn Expression {
        self.left.as_ref()
    }

    pub fn index(&self) -> &dyn Expression {
        self.index.as_ref()
    }
}

impl Deref for IndexExpression {
    type Target = NodeRoot;

    fn deref(&self) -> &Self::Target {
        &self.node
    }
}

impl Expression for IndexExpression {
    fn cast_to_node(&self) -> &dyn Node {
        &self.node
    }
}

//-----null表达式--------------------------------------
#[derive(Debug, Clone)]
pub struct Null {
    node: NodeRoot,
}

impl Null {
    pub fn new() -> Self {
        let node = NodeRoot::new("null".to_string(), "Null".to_string());
        Self { node }
    }
}

impl Deref for Null {
    type Target = NodeRoot;

    fn deref(&self) -> &Self::Target {
        &self.node
    }
}

impl Expression for Null {
    fn cast_to_node(&self) -> &dyn Node {
        &self.node
    }
}

//-----HashMap表达式--------------------------------------
#[derive(Debug, Clone)]
pub struct HashLiteral {
    node: NodeRoot,
    token: Token,
    keys: Vec<Box<dyn Expression>>,
    values: Vec<Box<dyn Expression>>,
}

impl Deref for HashLiteral {
    type Target = NodeRoot;

    fn deref(&self) -> &Self::Target {
        &self.node
    }
}

impl HashLiteral {
    pub fn new(
        token: Token,
        keys: Vec<Box<dyn Expression>>,
        values: Vec<Box<dyn Expression>>,
    ) -> Self {
        let mut literal = String::from("{");
        for (index, key) in keys.iter().enumerate() {
            let value = values.get(index);
            let value = if value.is_none() {
                Box::new(Null::new())
            } else {
                value.unwrap().clone()
            };
            literal.push_str(key.cast_to_node().get_literal());
            literal.push(':');
            literal.push_str(value.cast_to_node().get_literal());
            literal.push(',');
        }
        if keys.len() > 0 {
            let _ = literal.pop();
        }
        literal.push('}');
        let node = NodeRoot::new(literal, "HashLiteral".to_string());
        Self {
            node,
            token,
            keys,
            values,
        }
    }

    pub fn token(&self) -> &Token {
        &self.token
    }

    pub fn keys(&self) -> &Vec<Box<dyn Expression>> {
        &self.keys
    }

    pub fn values(&self) -> &Vec<Box<dyn Expression>> {
        &self.values
    }
}

impl Expression for HashLiteral {
    fn cast_to_node(&self) -> &dyn Node {
        &self.node
    }
}
